﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;

using Random = UnityEngine.Random;

/// <summary>
/// 十以内加法序列化数据
/// </summary>
public class TenPlusModule : MonoBehaviour
{
    #region 10以内加法简单文字说明
    //游戏一：赶羊回羊圈     |羊圈个数    羊种类            场景
    //章节1：一个集合增加    |   1           1(白)            牧场+1羊圈
    //章节2:两个集合合并     |   2           2(白&灰)         牧场+2羊圈
    //游戏二:剪羊毛          |羊种类      羊毛种类 
    //章节1：一个集合增加    |   1           1(白)            牧场
    //章节2:两个集合合并     |   2           2(白&灰)         牧场
    //游戏三：运羊毛                                          牧场
    #endregion

    #region 序列化数据

    //边界配置
    [SerializeField]
    private List<HardLevelEnum> _keys;
    [SerializeField]
    private List<OneDimensionBound> _values;

    public Dictionary<HardLevelEnum, OneDimensionBound> configdic = new Dictionary<HardLevelEnum, OneDimensionBound>();

    //游戏线
    [Header("[游戏线]")]
    public GamePlayLine gameplayline;
    #endregion

    #region 运行时数据
    [Header("[运行时数据]")]
    public TenPlusModuleRuntimeData runtimeData;
    #endregion

    //规定：所有面板上的数据都从1开始，程序内部从0开始[index]
    public const string tenplusmodule = "TenPlusModule";
    public const string defaultStr1 = "0,0,0";
    public const string hardLevelList = "HardLevelList";
    public const string defaultStr2 = "1,1,1,3@1";

    [Header("调试用[是否清除已保存数据]")]
    public bool IsClearData = false;

    //反序列化数据
    void UnSerialize()
    {
        if (IsClearData)
        {
            DataHelp.Save(tenplusmodule, defaultStr1);//动态数据[过程，当前游戏，当前回合]
            DataHelp.Save(hardLevelList, defaultStr2);//难度值
        }

        configdic.Clear();

        for (int i = 0; i < Mathf.Min(_keys.Count, _values.Count); i++)
            configdic.Add(_keys[i], _values[i]);
        
        string localStr = DataHelp.Load(tenplusmodule, defaultStr1);
        string[] listStr = localStr.Split(',');
        gameplayline.finishedLearnProcedureTimes = int.Parse(listStr[0]);
        runtimeData.currentLearnProcedureIndex = gameplayline.finishedLearnProcedureTimes+1;
        runtimeData.currentGameIndex = int.Parse(listStr[1]);
        runtimeData.currentRoundIndex = int.Parse(listStr[2]);
        

        List<int> hardLevelInt;
        //规则：前六次游戏难度为简单*4，简单*4，普通*4，普通*4，难*4，难*4
        //第七次开始难度随机 [简单,普通,难](顺序随机)+随机难度
        //每一次学习过程的难度共享
        if (runtimeData.currentLearnProcedureIndex >= 1 && runtimeData.currentLearnProcedureIndex <= 2)
        {
            hardLevelInt = new List<int> { 1, 1, 1, 1 };
        }
        else if (runtimeData.currentLearnProcedureIndex <= 4)
        {
            hardLevelInt = new List<int> { 2, 2, 2, 2 };
        }
        else if (runtimeData.currentLearnProcedureIndex <= 6)
        {
            hardLevelInt = new List<int> { 3, 3, 3, 3 };
        }
        else
        {
            string getStr = DataHelp.Load(hardLevelList, defaultStr2);
            if (getStr == "")
            {
                getStr = GetNewHardLevelStr(runtimeData.currentLearnProcedureIndex);
                DataHelp.Save(hardLevelList, getStr);
            }

            hardLevelInt = new List<int>();
            string[] splitStr = getStr.Split('@');
            string[] hardLevelStrList;
            if (int.Parse(splitStr[1]) == runtimeData.currentLearnProcedureIndex)
            {
                hardLevelStrList = splitStr[0].Split(',');
            }
            else
            {
                getStr = GetNewHardLevelStr(runtimeData.currentLearnProcedureIndex);
                DataHelp.Save(hardLevelList, getStr);
                hardLevelStrList = getStr.Split('@')[0].Split(',');
            }
            for (int i = 0; i < hardLevelStrList.Length; i++)
            {
                hardLevelInt.Add(int.Parse(hardLevelStrList[i]));
            }
        }
        
        for (int i=0;i<gameplayline.games.Count;i++)
        {
            for (int j=0;j<gameplayline.games[i].gameround.Count;j++)
            {
                gameplayline.games[i].gameround[j].hardlevel = (HardLevelEnum)hardLevelInt[j];
                
            }
        }
    }


    string GetNewHardLevelStr(int currentProcedureIndex)
    {
        int[] array = { 1, 2, 3 };
       MathHelp.Shuffle(array, 2);
        string defaultArrayStr = "";
        for (int i = 0; i < array.Length; i++)
            defaultArrayStr += array[i] + ",";
        int lastHardLevel = Random.Range(1,4);
        defaultArrayStr += lastHardLevel + "@" + runtimeData.currentLearnProcedureIndex;
        return defaultArrayStr;
    }
    

    #region 外部接口
    //数据已经准备好
    public void GetReady()
    {
        UnSerialize();
    }

    public TenPlusModuleRuntimeData GetRuntimeData()
    {
        
        return this.runtimeData;
    }

    /// <summary>
    /// 外部接口，动态数据保存
    /// 之后reload.
    /// </summary>
    /// <param name="dynamicData"></param>
    public void Save(string dynamicData)
    {
        DataHelp.Save(tenplusmodule, dynamicData);//动态数据
        
    }

    //根据难度级别获取随机算式结果值
    public int GetRandomSumByHardlevel(HardLevelEnum hl,int lastSum)
    {
        OneDimensionBound bound = configdic[hl];
        int result = 0;
        int num = 100;
        while ((--num)>0)
        {
            result = UnityEngine.Random.Range(bound.from, bound.to + 1);
            if (result != lastSum)
                return result;
        }
        return lastSum;
    }

    //退出时设置数据为刚开始[第一个游戏]
    public void SetDataToOrgin()
    {
        string[] strArray = DataHelp.Load(tenplusmodule, defaultStr1).Split(',');
        DataHelp.Save(tenplusmodule, string.Format("{0},{1},{2}",strArray[0], "0", "0"));
    }
    #endregion

    private void OnDestroy()    {
        SetDataToOrgin();
    }
}

[System.Serializable]
public class GamePlayLine
{
    //已经完成的学习过程
    public int finishedLearnProcedureTimes = 0;

    public List<TenPlusGame> games;
    [Header("[一个学习过程中难度规则是否相似]")]
    public bool isHardLevelCopyInOneProcedure = true;

    //private List<HardLevelEnum> hardLevelCopyData;

    public GamePlayLine() { }


}
[System.Serializable]
public class TenPlusGame
{
    //游戏名称
    public string gamename="";
    
    [Header("[回合]")]
    public List< GameRound > gameround=new List<GameRound>();

    public TenPlusGame() { }
    
}

[System.Serializable]
public class GameRound
{
    //难度分级
    [Header("[难易度]")]
    public HardLevelEnum hardlevel = HardLevelEnum.easy;

    //是否有羊圈
    [Header("[是否有羊圈]")]
    public bool hasSheepfold = false;
    [Header("羊圈数量")]
    public int sheepfoldNum = 1;

    //是否有卡车
    [Header("[是否有卡车]")]
    public bool hasCar = false;

    //羊的种类
    [Header("[羊的种类]")]
    public int sheepTypes = 1;

    public GameRound() { }
}

public enum HardLevelEnum
{
    easy = 1,       //简单
    normal = 2,     //普通
    hard = 3,       //难
    random      //随机
}
[System.Serializable]
public class OneDimensionBound
{
    public int from;
    public int to;
    public OneDimensionBound(int f,int t)
    {
        from = f;
        to = t;
    } 
}

[System.Serializable]
public class TenPlusModuleRuntimeData
{
    //当前是第几次学习过程
    public int currentLearnProcedureIndex = 0;

    //当前小游戏在模组线中的索引
    public int currentGameIndex;
    //当前回合
    public int currentRoundIndex;

    public TenPlusModuleRuntimeData()
    {
        currentGameIndex = 0;
        currentRoundIndex = 0;
    }
}

public class DataHelp
{
    public static void Save(string keyStr,string str)
    {
        PlayerPrefs.SetString(keyStr, str);
    }

    public static string Load(string keyStr,string defaultStr)
    {
        return PlayerPrefs.GetString(keyStr, defaultStr);
    }
}


[Serializable]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    [SerializeField, HideInInspector]
    private List<TKey> _serializedKeys = new List<TKey>();
    [SerializeField, HideInInspector]
    private List<TValue> _serializedValues = new List<TValue>();
    [SerializeField, HideInInspector]
    private bool _isSerializing;
    [SerializeField, HideInInspector]
    private int _serializedCount;

    public IList<TKey> SerializedKeys
    {
        get { return _serializedKeys.AsReadOnly(); }
    }

    public IList<TValue> SerializedValues
    {
        get { return _serializedValues.AsReadOnly(); }
    }

    public bool IsSerializing { get { return _isSerializing; } }

    [Obsolete("Manual call not supported.", true)]
    public void OnBeforeSerialize()
    {
        _isSerializing = true;
        _serializedKeys.Clear();
        _serializedValues.Clear();

        _serializedValues.Capacity = Count;
        _serializedKeys.Capacity = Count;

        foreach (var item in this)
        {
            _serializedKeys.Add(item.Key);
            _serializedValues.Add(item.Value);
        }

        _serializedCount = Count;
    }

    [Obsolete("Manual call not supported.", true)]
    public void OnAfterDeserialize()
    {
        Clear();

        if (_serializedCount != _serializedKeys.Count)
        {
            throw new SerializationException(string.Format("{0} failed to serialize.", typeof(TKey).Name));
        }
        if (_serializedCount != _serializedValues.Count)
        {
            throw new SerializationException(string.Format("{0} failed to serialize.", typeof(TValue).Name));
        }

        for (var i = 0; i < _serializedCount; ++i)
        {
            Add(_serializedKeys[i], _serializedValues[i]);
        }

        _isSerializing = false;

        _serializedKeys.Clear();
        _serializedValues.Clear();
    }
}